using System;
using System.Text;
using ICalendar.CalendarProperties;
using AttachmentCollection=ICalendar.CalendarProperties.AttachmentCollection;

namespace ICalendar
{
    //TODO: Adicionar suporte a recurrence events
    public class Event
    {

        public UniqueIdentifier EventId { get; set; }
        public DateTimeStart StartDate { get; set; }
        public DateTimeEnd EndDate { get; set; }
        public Created Created { get; set; }
        public bool AllDayEvent { get; set; }
        public RecurrenceId RecurrenceId { get; set; }
        //Title
        public Summary Summary { get; set; }

        public Description Description { get; set; }
    
        public string TimeZoneId { get; set; }

        //optional - MUST NOT occur more than once
        /// <summary>
        /// This property defines the access classification for a calendar component. 
        /// </summary>
        public Classification Classification { get; set; }
        /// <summary>
        /// This property defines a Uniform Resource Locator (URL) associated with the iCalendar object.
        /// </summary>
        public Url Url { get; set; }
        public Organizer Organizer { get; set; }
        //public MailAddress SentBy { get; set; }

        //optional - MAY occur more than once
        public AttendeeCollection Attendees { get; set; }
        public AttachmentCollection Attachments { get; set; }
        /// <summary>
        /// This property specifies non-processing information intended to provide a comment to the calendar user.
        /// </summary>
        public CommentCollection Comments { get; set; }
        public ContactCollection Contacts { get; set; }
        public Categories Categories { get; set; }
        public Geo Geo { get; set; }
        public LastModified LastModified { get; set; }
        public Location Location { get; set; }
        public Priority Priority { get; set; }
        public DateTimeStamp DateTimeStamp { get; set; }
        // aka Version
        public Sequence Sequence { get; set; }
        public Status<EventStatusValue?> Status { get; set; }
        /// <summary>
        /// This property defines whether an event is transparent or not to busy time searches.
        /// </summary>
        public Transparent Transparent { get; set; }

        //ALARMS
        public AlarmCollection Alarms { get; set; }

        public Event(string summary, DateTime startDate, DateTime endDate) : this(summary,startDate,endDate, null)
        {
            
        }

        public Event(string summary, DateTime startDate, DateTime endDate, UniqueIdentifier eventId)
        {
            if (string.IsNullOrEmpty(summary))
            {
                throw new ArgumentNullException("summary");
            }

            this.EventId = eventId;
            this.Priority = new Priority();
            this.Sequence = new Sequence();
            this.DateTimeStamp = new DateTimeStamp();
            this.Summary = summary;
            this.StartDate = new DateTimeStart(startDate);
            this.EndDate = new DateTimeEnd(endDate);
            this.Alarms = new AlarmCollection();
            this.TimeZoneId = TimeZoneInfo.Local.Id;
            this.Attendees = new AttendeeCollection();
            this.Attachments = new AttachmentCollection();
            this.Contacts = new ContactCollection();
            this.DateTimeStamp = new DateTimeStamp();
            //Default: Public
            this.Classification = new Classification();
            
        }

        public string ToString(string method)
        {
            return WriteEvent(this, method);
        }

        public override string ToString()
        {
            return WriteEvent(this, null);
        }
        
        private static string WriteEvent(Event eventObj, string method)
        {
            bool allDay = eventObj.AllDayEvent;
            //DateTime start = @eventObj.StartDate;
            //DateTime end = @eventObj.EndDate;

            var strEvent = new StringBuilder();

            // Event header
            strEvent.Append(Util.Write("BEGIN", "VEVENT"));

            //Attendees - No exists Attendees to a Publish Method
            if (method.ToUpperInvariant() != MethodNames.Publish)
            {
                strEvent.Append(eventObj.Attendees.ToString());
            }
            // Title - Summary
            strEvent.Append(eventObj.Summary);

            // Location
            strEvent.Append(eventObj.Location);

            // Description
            strEvent.Append(eventObj.Description);

            // ORGANIZER
            if (eventObj.Organizer != null)
                strEvent.Append(eventObj.Organizer);
                  
            // TRANSP
            strEvent.Append(eventObj.Transparent);
            
            // Created date
            strEvent.Append(eventObj.Created);

            //DateTime Stamp
            strEvent.Append(eventObj.DateTimeStamp);

            //Last-Modified
             strEvent.Append(eventObj.LastModified);

            //Priority
            strEvent.Append(eventObj.Priority);

            //Status
            strEvent.Append(eventObj.Status);

            //UID
            strEvent.Append(eventObj.EventId);
            
            // Sequence (aka version)
            strEvent.Append(eventObj.Sequence);

            // URL
            strEvent.Append(Util.Write("URL;VALUE=URI", eventObj.Url));

            // Duration if we're an all-day eventObj
            if (allDay)
            {
                // All-day events always end at :59, so we have to add one minute for this to work correctly
                strEvent.Append(Util.Write("DURATION", string.Format("P{0}D", (eventObj.EndDate.Value.AddMinutes(1) - eventObj.StartDate.Value).Days)));
            }

            // Start date (different format if all-day eventObj)
            //DTSTART
            if (allDay)
            {
                eventObj.StartDate.ValueType = ValueType.Date;
                strEvent.Append(eventObj.StartDate);
                //strEvent.Append(Util.Write("DTSTART;VALUE=DATE", start.ToString("yyyyMMdd")));
            }
            else
            {
                //strEvent.Append(Util.Write("DTSTART;TimeZoneId=" + @eventObj.TimeZoneId, Util.ToDateTimeString(start)));
                strEvent.Append(eventObj.StartDate);
                //strEvent.Append(Util.Write("DTSTART", start.ToICalendarUniversalTimeString()));
            }

            // End date (only if not an all-day eventObj)
            //DTEND
            if (!allDay)
            {
                strEvent.Append(eventObj.EndDate);
                //strEvent.Append(Util.Write("DTEND", end.ToICalendarUniversalTimeString()));
                ////strEvent.Append(Util.Write("DTEND;TimeZoneId=" + @eventObj.TimeZoneId,  Util.ToDateTimeString(end)));
            }

            //ADD RECURS AKI

            //RECURRENCE ID 
            strEvent.Append(eventObj.RecurrenceId);

            //ALARMS
            strEvent.Append(eventObj.Alarms.ToString());


            //CLASS
            strEvent.Append(eventObj.Classification);

            //GEO
            strEvent.Append(eventObj.Geo);

            //CONTACTS
            strEvent.Append(eventObj.Contacts);
            
            //ATTACHS
            strEvent.Append(eventObj.Attachments);

            //COMMENTS
            strEvent.Append(eventObj.Comments);
            
                // Event footer
            strEvent.Append(Util.Write("END", "VEVENT"));

         
            return strEvent.ToString();
        }
    }

    
}
